import { component$ } from '@builder.io/qwik';
import { type DocumentHead, routeAction$, routeLoader$, z, zod$, useNavigate } from '@builder.io/qwik-city';
import _ from 'lodash';
import { toBigint } from '~/common/bigint';
import { QPostEditor } from '~/integrations/react/post-editor';
import { getUserId, shouldAuth } from '~/server/authn';
import { db } from '~/server/db';
import { sha1hex } from '~/server/hash';
import logger from '~/server/logger';
import { createTag, searchTags } from './server';
import { postCollectionService } from '~/server/service/post-collection-service';
import { postService } from '~/server/service/post-service';

export const useLoader = routeLoader$(async (requestEvent) => {
  const userId = getUserId(requestEvent);

  const cidStr = requestEvent.query.get('collectionId') || '';
  if (_.isEmpty(cidStr)) {
    logger.error(`==> ${requestEvent.pathname}: no id`);
    throw requestEvent.redirect(307, '/me/post-collections');
  }

  const cid = toBigint(cidStr, () => requestEvent.redirect(307, '/me/post-collections'));

  const collecion = await postCollectionService.findByIdAndUserId(db, cid, userId);
  if (!collecion) {
    throw requestEvent.redirect(307, '/me/post-collections');
  }

  return collecion;
});

export const useCreatePostAction = routeAction$(
  async (props, requestEvent) => {
    await shouldAuth(requestEvent);
    const userId = getUserId(requestEvent);

    const { collectionId, title, content } = props;
    const cid = toBigint(collectionId, () => requestEvent.redirect(307, '/me/post-collections'));

    const post = await postService.create(db, {
      title,
      content,
      collectionId: cid,
      userId,
      type: 'MD',
      dedupKey: sha1hex(collectionId + title + content + userId.toString),
      tagIds: [], // TODO: 创建时指定标签
    });

    logger.info(`==> ${requestEvent.pathname}: create post ${post.id.toString()}`);
    return { id: post.id };
  },
  zod$(
    z.object({
      collectionId: z.string().regex(/^[1-9][0-9]?$/, { message: 'id不合法' }),
      title: z
        .string()
        .min(1, { message: '标题至少应包含一个字符。' })
        .max(200, { message: '标题不可超过200个字符。' }),
      content: z
        .string()
        .min(1, { message: '正文至少应包含一个字符。' })
        .max(20000, { message: '正文不可超过20000个字符。' }),
    })
  )
);

export default component$(() => {
  const collectionSignal = useLoader();
  const navigate = useNavigate();
  const createPost = useCreatePostAction();
  const collectionIdStr = collectionSignal.value.id.toString();
  return (
    <div>
      <h1 class="text-xl font-bold text-kq-900 my-4">创建文章</h1>
      <QPostEditor
        onSearchTags$={async (tagName) => {
          try {
            const tags = await searchTags(tagName);
            return { ok: true, data: tags };
          } catch (e) {
            return { ok: false, error: (e as Error).message || '未知错误' };
          }
        }}
        onCreateTag$={async (tagName) => {
          try {
            const t = await createTag(tagName);
            return { ok: true, data: t };
          } catch (e) {
            return { ok: false, error: (e as Error).message || '未知错误' };
          }
        }}
        client:only
        data={{ title: '', content: '', tags: [] }}
        onSave$={async ({ title, content }) => {
          const result = await createPost.submit({
            collectionId: collectionIdStr,
            title,
            content,
          });
          if (result.value.failed) {
            const { fieldErrors, formErrors } = result.value;
            const errorMessage = _(fieldErrors)
              .values()
              .map((it) => (_.isNil(it) ? [] : it))
              .flatten()
              .concat(formErrors)
              .first();
            throw new Error(errorMessage || '未知错误');
          } else {
            navigate(`/posts/${result.value.id.toString()}`);
          }
        }}
      />
    </div>
  );
});

export const head: DocumentHead = {
  title: '创建文章',
};
